﻿//
// Created by Grishul Eugeny
//
// See license in License.txt
//

using System;
using System.Windows.Forms;
using System.Linq;
using System.IO;
using NCommander.Core;
using NCommander.NodeProviders;
using System.Drawing;
using System.ServiceProcess;
using System.ComponentModel;
using System.Collections.Generic;
using System.Reflection;

namespace NCommander
{
	public partial class ServicesView : UserControl, IViewProvider
	{
		private ServiceProvider _nodeProvider = new ServiceProvider();
		private ServiceProvider.ServiceNode[] _controllers = new ServiceProvider.ServiceNode[0];

		public ServicesView()
		{
			InitializeComponent();
			_nodes.DisableFlicker();

			_controllers = _nodeProvider.GetNodes().Cast<ServiceProvider.ServiceNode>().ToArray();
			_nodes.RowCount = _controllers.Length;

			_nodeProvider.Refresh += _refreshTimer_Tick;
		}

		private void _action_Opening( object sender, System.ComponentModel.CancelEventArgs e )
		{
			e.Cancel = SelectedNodes.Length == 0;
		}

		private void _action_Opened( object sender, EventArgs e )
		{
			var controller = ( SelectedNodes[0] as ServiceProvider.ServiceNode ).Controller;

			_startToolStripMenuItem.Visible = controller.Status != ServiceControllerStatus.Running && controller.Status != ServiceControllerStatus.ContinuePending && controller.Status != ServiceControllerStatus.StartPending;
			_stopToolStripMenuItem.Visible = controller.CanStop;
			_pauseToolStripMenuItem.Visible = controller.CanPauseAndContinue;
		}

		private void _columnsSelection_Opening( object sender, CancelEventArgs e )
		{
			_statusToolStripMenuItem.Checked = _statusColumn.Visible;
			_displayNameToolStripMenuItem.Checked = _displayNameColumn.Visible;
			_imagePathToolStripMenuItem.Checked = _imagePathColumn.Visible;
			_logOnAsToolStripMenuItem.Checked = _logOnAsColumn.Visible;
			_startupToolStripMenuItem.Checked = _startupColumn.Visible;
		}

		private void _columnsSelection_ItemClicked( object sender, ToolStripItemClickedEventArgs e )
		{
			DataGridViewColumn column = null;

			if( e.ClickedItem == _statusToolStripMenuItem )
				column = _statusColumn;
			else if( e.ClickedItem == _displayNameToolStripMenuItem )
				column = _displayNameColumn;
			else if( e.ClickedItem == _logOnAsToolStripMenuItem )
				column = _logOnAsColumn;
			else if( e.ClickedItem == _imagePathToolStripMenuItem )
				column = _imagePathColumn;
			else if( e.ClickedItem == _startupToolStripMenuItem )
				column = _startupColumn;

			column.Visible = !column.Visible;
		}
		#region IViewProvider Members

		public Node[] SelectedNodes
		{
			get { return _nodes.SelectedRows.Cast<DataGridViewRow>().Select( x => ( Node ) _controllers[x.Index] ).ToArray(); }
			set { throw new NotImplementedException(); }
		}

		public NodeProvider NodeProvider
		{
			get { return _nodeProvider; }
			set { _nodeProvider = ( ServiceProvider ) value; }
		}

		public void SelectAll()
		{
			_nodes.SelectAll();
		}

		public string TabCaption { get { return "Windows Services"; } }

		public event EventHandler TabCaptionChanged;

		#endregion

		private void _refreshTimer_Tick( object sender, EventArgs e )
		{
			var newControllers = SortAccordingColumnGlyph( _nodeProvider.GetNodes().Cast<ServiceProvider.ServiceNode>().ToArray() );

			_controllers = newControllers;
			_nodes.RowCount = _controllers.Length;
			_nodes.Refresh();
		}

		private void _startToolStripMenuItem_Click( object sender, EventArgs e )
		{
			foreach( ServiceProvider.ServiceNode node in SelectedNodes )
				node.Controller.Start();
		}

		private void _stopToolStripMenuItem_Click( object sender, EventArgs e )
		{
			foreach( ServiceProvider.ServiceNode node in SelectedNodes )
				node.Controller.Stop();
		}

		private void _pauseToolStripMenuItem_Click( object sender, EventArgs e )
		{
			foreach( ServiceProvider.ServiceNode node in SelectedNodes )
				node.Controller.Pause();
		}

		private void _nodes_CellValueNeeded( object sender, DataGridViewCellValueEventArgs e )
		{
			var service = _controllers[e.RowIndex];
			var currentColumn = _nodes.Columns[e.ColumnIndex];

			if( currentColumn == _imageColumn )
			{
				string imageKey = null;

				if( service.Controller.Status == ServiceControllerStatus.Running || service.Controller.Status == ServiceControllerStatus.StartPending )
					imageKey = "Running.ico";
				else if( service.Controller.Status == ServiceControllerStatus.Stopped || service.Controller.Status == ServiceControllerStatus.StopPending )
					imageKey = "Stopped.ico";
				else if( service.Controller.Status == ServiceControllerStatus.Paused || service.Controller.Status == ServiceControllerStatus.PausePending || service.Controller.Status == ServiceControllerStatus.ContinuePending )
					imageKey = "Paused.ico";

				e.Value = _icons.Images[imageKey];
			}
			else if( currentColumn == _displayNameColumn )
				e.Value = service.Controller.DisplayName;
			else if( currentColumn == _serviceNameColumn )
				e.Value = service.Controller.ServiceName;
			else if( currentColumn == _statusColumn )
				e.Value = service.Controller.Status.ToString();
			else if( currentColumn == _imagePathColumn )
				e.Value = service.ImagePath;
			else if( currentColumn == _startupColumn )
				e.Value = service.StartupType;
			else if( currentColumn == _logOnAsColumn )
				e.Value = service.LogOnAs;
		}

		private void _nodes_CellContextMenuStripNeeded( object sender, DataGridViewCellContextMenuStripNeededEventArgs e )
		{
			if( e.ColumnIndex >= 0 && e.RowIndex == -1 )
				e.ContextMenuStrip = _columnsSelection;
			else
			{
				e.ContextMenuStrip = _action;

				foreach( DataGridViewRow item in _nodes.Rows )
					item.Selected = false;

				_nodes.Rows[e.RowIndex].Selected = true;
			}
		}

		private void _nodes_CellClick( object sender, DataGridViewCellEventArgs e )
		{
			if( e.ColumnIndex >= 0 && e.RowIndex == -1 )
			{
				var currentColumn = _nodes.Columns[e.ColumnIndex];

				foreach( DataGridViewColumn column in _nodes.Columns )
					if( column != currentColumn )
						column.HeaderCell.SortGlyphDirection = SortOrder.None;

				if( currentColumn.HeaderCell.SortGlyphDirection == SortOrder.None )
					currentColumn.HeaderCell.SortGlyphDirection = SortOrder.Ascending;
				else
					currentColumn.HeaderCell.SortGlyphDirection ^= ( SortOrder ) 3;

				_controllers = SortAccordingColumnGlyph( _controllers );

				_nodes.Refresh();
			}
		}

		private ServiceProvider.ServiceNode[] SortAccordingColumnGlyph( ServiceProvider.ServiceNode[] controllers )
		{
			var currentColumn = _nodes.Columns.Cast<DataGridViewColumn>().FirstOrDefault( x => x.HeaderCell.SortGlyphDirection != SortOrder.None );
			if( currentColumn == null )
				return controllers;

			Func<ServiceProvider.ServiceNode, object> sorter = null;

			if( currentColumn == _statusColumn || currentColumn == _imageColumn )
				sorter = x => ( object ) ( x.Controller.Status ^ ( ServiceControllerStatus ) 7 );
			else if( currentColumn == _displayNameColumn )
				sorter = x => ( object ) x.Controller.DisplayName;
			else if( currentColumn == _serviceNameColumn )
				sorter = x => x.Controller.ServiceName;
			else if( currentColumn == _imagePathColumn )
				sorter = x => x.ImagePath;
			else if( currentColumn == _startupColumn )
				sorter = x => x.StartupType;
			else if( currentColumn == _logOnAsColumn )
				sorter = x => x.LogOnAs;

			if( currentColumn.HeaderCell.SortGlyphDirection == SortOrder.Ascending )
				return controllers.OrderBy( sorter ).ToArray();
			else
				return controllers.OrderByDescending( sorter ).ToArray();
		}

		private void _nodes_CellDoubleClick( object sender, DataGridViewCellEventArgs e )
		{
			NodeProvider.OnExecute( SelectedNodes[0] );
		}

		private void _newServiceToolStripMenuItem_Click( object sender, EventArgs e )
		{
			new NewService().ShowDialog( this );
		}
	}
}
